View Javadoc
1   package edu.jiangxin.apktoolbox.file.password.recovery.category.bruteforce;
2   
3   import edu.jiangxin.apktoolbox.file.password.recovery.RecoveryPanel;
4   import edu.jiangxin.apktoolbox.file.password.recovery.State;
5   import edu.jiangxin.apktoolbox.file.password.recovery.category.ICategory;
6   import edu.jiangxin.apktoolbox.file.password.recovery.checker.FileChecker;
7   import edu.jiangxin.apktoolbox.file.password.recovery.checker.IChecker;
8   import org.apache.commons.lang3.StringUtils;
9   import org.apache.logging.log4j.LogManager;
10  import org.apache.logging.log4j.Logger;
11  
12  import javax.swing.*;
13  import java.util.concurrent.ExecutorService;
14  import java.util.concurrent.Executors;
15  import java.util.concurrent.TimeUnit;
16  
17  public class BruteForceProxy implements ICategory {
18      private static final Logger logger = LogManager.getLogger(BruteForceProxy.class.getSimpleName());
19  
20      private ExecutorService executorService;
21  
22      private BruteForceFuture bruteForceFuture;
23  
24      private static class BruteForceProxyHolder {
25          private static final BruteForceProxy instance = new BruteForceProxy();
26      }
27  
28      private BruteForceProxy() {
29      }
30  
31      public static BruteForceProxy getInstance() {
32          return BruteForceProxyHolder.instance;
33      }
34  
35      private String startAndGet(int numThreads, int passwordLength, IChecker checker, String charsSet, RecoveryPanel panel) {
36          executorService = Executors.newFixedThreadPool(numThreads);
37          bruteForceFuture = new BruteForceFuture(numThreads);
38          BruteForceTaskParam param = new BruteForceTaskParam(numThreads, passwordLength, checker, charsSet);
39          for (int taskId = 0; taskId < numThreads; taskId++) {
40              BruteForceRunnable task = new BruteForceRunnable(taskId, param, bruteForceFuture, panel);
41              executorService.execute(task);
42          }
43          String password = null;
44          try {
45              password = bruteForceFuture.get();
46          } catch (Exception e) {
47              logger.info("Exception test: ", e);
48          } finally {
49              if (executorService.isShutdown()) {
50                  executorService.shutdown();
51              }
52          }
53          return password;
54      }
55  
56      @Override
57      public void start(RecoveryPanel panel) {
58          String charset = panel.getCharset();
59          logger.info("Charset: {}", charset);
60          if (StringUtils.isEmpty(charset)) {
61              JOptionPane.showMessageDialog(panel, "Character set is empty!");
62              return;
63          }
64  
65          int minLength = panel.getMinLength();
66          int maxLength = panel.getMaxLength();
67          if (minLength > maxLength) {
68              JOptionPane.showMessageDialog(panel, "Minimum length is bigger than maximum length!");
69              return;
70          }
71          String password = null;
72          int totalNumber = 0;
73          for (int length = minLength; length <= maxLength; length++) {
74              totalNumber += (int)Math.pow(charset.length(), length);
75          }
76          panel.resetProgressMaxValue(totalNumber);
77          for (int length = minLength; length <= maxLength; length++) {
78              long startTime = System.currentTimeMillis();
79              FileChecker fileChecker = panel.getCurrentFileChecker();
80              int processorCount = Runtime.getRuntime().availableProcessors();
81              int numThreads = getThreadCount(charset.length(), length, processorCount);
82              logger.info("[{}]Current attempt length: {}, thread number: {}", fileChecker, length, numThreads);
83              password = startAndGet(numThreads, length, fileChecker, charset, panel);
84              long endTime = System.currentTimeMillis();
85              logger.info("Current attempt length: {}, Cost time: {}ms", length, (endTime - startTime));
86              if (password != null || panel.getCurrentState() != State.WORKING) {
87                  logger.info("Break state: {}", panel.getCurrentState());
88                  break;
89              }
90          }
91          panel.showResultWithDialog(password);
92      }
93  
94      @Override
95      public void cancel() {
96          if (bruteForceFuture != null) {
97              bruteForceFuture.cancel(false);
98          }
99          if (executorService != null && !executorService.isShutdown()) {
100             executorService.shutdown();
101         }
102         while (executorService != null && !executorService.isTerminated()) {
103             try {
104                 final boolean isTimeout = !executorService.awaitTermination(100, TimeUnit.SECONDS);
105                 logger.info("awaitTermination isTimeout: " + isTimeout);
106             } catch (InterruptedException e) {
107                 logger.error("awaitTermination InterruptedException");
108                 Thread.currentThread().interrupt();
109             }
110         }
111     }
112 
113     private int getThreadCount(int charSetSize, int length, int maxThreadCount) {
114         int result = 1;
115         for (int i = 1; i <= length; i++) {
116             result *= charSetSize;
117             if (result >= maxThreadCount) {
118                 return maxThreadCount;
119             }
120         }
121         return result;
122     }
123 }